package com.billard.config;

import com.billard.mapper.UserMapper;
import com.billard.properties.JwtProperties;
import com.billard.result.Result;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import jakarta.servlet.http.HttpServletResponse;


@Configuration
@Slf4j
@EnableGlobalMethodSecurity(prePostEnabled = true)  // 关键！
public class SecurityConfig {

    private final JwtProperties jwtProperties; // JWT 配置类，保存 token 名称和 secret
    private final UserMapper userMapper; // 数据库操作类，用于查用户权限
    private final ObjectMapper objectMapper = new ObjectMapper();

    public SecurityConfig(JwtProperties jwtProperties,
                          UserMapper userMapper) {
        this.jwtProperties = jwtProperties;
        this.userMapper = userMapper;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                // -------------------------------
                // 关闭 CSRF、默认登录页面、HTTP Basic
                // -------------------------------
                .csrf(csrf -> csrf.disable())          // 关闭跨站请求伪造保护（Postman 或 Swagger 测试需要）
                .formLogin(form -> form.disable())     // 禁用 Spring Security 默认登录页面
                .httpBasic(httpBasic -> httpBasic.disable()) // 禁用 HTTP Basic 弹窗认证

                // -------------------------------
                // 设置请求权限
                // -------------------------------
                .authorizeHttpRequests(auth -> auth
                        // 登录接口直接放行
                        .requestMatchers("/user/login", "/user/create").permitAll()
                        // swagger 文档、静态资源放行
                        .requestMatchers(
                                "/health/**",
                                "/doc.html/**",
                                "/resources/**",
                                "/META-INF/resources/**",
                                "/v3/api-docs/**",
                                "/swagger-resources/**",
                                "/webjars/**",
                                "/swagger-ui/**"
                        ).permitAll()
                        // 其他接口都需要认证（登录）
                        .anyRequest().authenticated()
                )
                // -------------------------------
                // 注册自定义 JWT 过滤器
                // -------------------------------
                // 过滤器顺序：放在 UsernamePasswordAuthenticationFilter 前面
                // 用于解析 JWT，验证 token，并把用户信息存入 SecurityContext
                .addFilterBefore(
                        new JwtAuthenticationFilter(jwtProperties, userMapper),
                        org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.class
                )
                .exceptionHandling(ex -> ex
                        // 未登录
                        .authenticationEntryPoint((request, response, authException) -> {
                            log.warn("用户未登录或 JWT 认证失败，URI: {}", request.getRequestURI());
                            response.setContentType("application/json;charset=UTF-8");
                            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                            Result<Void> result = Result.error(401, "未登录或认证失败");
                            response.getWriter().write(objectMapper.writeValueAsString(result));
                        })
                        // 权限不足 - 移除自定义处理，让全局异常处理器处理
                        /*.accessDeniedHandler((request, response, accessDeniedException) -> {
                            log.warn("权限不足，用户: {}，URI: {}",
                                    request.getUserPrincipal() != null ? request.getUserPrincipal().getName() : "匿名",
                                    request.getRequestURI());
                            response.setContentType("application/json;charset=UTF-8");
                            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
                            Result<Void> result = Result.error(403, "权限不足，无法访问该资源");
                            response.getWriter().write(objectMapper.writeValueAsString(result));
                        })*/
                );


        log.info("SecurityConfig 配置完成");
        return http.build();
    }
}
